home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
PASCAL
/
MISC_ROU
/
RANDOM.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1991-02-23
|
4KB
|
122 lines
UNIT RandomNumbers;
{ This unit implements a "minimal standard" random number generator
whose parameters are optimal for 32-bit arithmetic. This is not the
"best" random number generator possible, but it is simple, quick,
and produces numbers which are "random" enough for most purposes.
It is based on the "parametric multiplicative linear congruential
algorithm" which was originally proposed by D. H. Lehmer in 1951.
This algorithm generates a sequence of integers z[1], z[2], z[3]...
by repeatedly carrying out the following calculation:
z[n+1] = (a * z[n]) mod m
where "a" and "m" are suitable constants. The successive "z"s are
stored in the variable "seed" in this unit. They all lie in the
range [0..m-1], so dividing them by "m" gives real numbers which
lie in the range [0..1].
In 1969, Lewis, Goodman and Miller proposed the choice of a = 16807
and m = 2**31 - 1 = 2147483647 as particularly suited for a machine
with a 32-bit word length (in their case, the IBM System/360).
The main problem is that a * z[n] can be more than 32 bits long,
leading to integer overflow on many systems (including the Mac).
In 1979, G. L. Schrage devised an implementation of the LG&M method
which is guaranteed not to produce integer overflow on any system
with a 32-bit word length. It is this implementation which is
used here, in function "RandomReal".
Source: Stephen K. Park and Keith W. Miller, "Random Number
Generators: Good Ones Are Hard to Find", Communications of the ACM,
vol. 31, p. 1192 (October 1988).
This unit was written in MPW Pascal, v3.1.
Submitted by: Jon Bell
Dept. of Physics & Comp. Sci.
Presbyterian College
Clinton SC 29325
CIS #70441,353 }
INTERFACE
procedure InitRandomSeed (newSeed : longint);
{ Initializes the random number seed to "newSeed". You must call this
procedure once, at the beginning of your program, before you use
either of the following functions. As far as randomness is concerned,
it makes no difference what value you use for "newSeed", so long
as it isn't zero. Using different seeds merely gives you different
sequences of "random" numbers. Using the same seed each time you
run the program gives you the same sequence of "random" numbers
each time, which may be useful for debugging. }
function RandomReal : real;
{ Returns a real number, "randomly" selected from the interval [0,1]. }
function RandomInteger (max : integer) : integer;
{ Returns an integer, "randomly" selected from the interval [1,max]. }
{-----------------------------------------------------------------------}
{-----------------------------------------------------------------------}
IMPLEMENTATION
var
seed : longint;
{-----------------------------------------------------------------------}
procedure InitRandomSeed (newSeed : longint);
begin
seed := newSeed
end;
{-----------------------------------------------------------------------}
function RandomReal : real;
const
a = 16807;
m = 2147483647;
q = 127773;
r = 2836;
var
lo, hi, test : longint;
begin
hi := seed div q;
lo := seed mod q;
test := a * lo - r * hi;
if test > 0 then
seed := test
else
seed := test + m;
RandomReal := seed / m
end;
{-----------------------------------------------------------------------}
function RandomInteger (max : integer) : integer;
var
result : integer;
begin
result := trunc (RandomReal * max) + 1;
if result > max then
RandomInteger := max { This doesn't happen very often. }
else
RandomInteger := result
end;
{-----------------------------------------------------------------------}
END.